import React, { useEffect, useMemo, useState } from "react";
import { withLoading } from "./withLoading";
import type { IWithLoadingOption, IWithLoadingApi, ITargetComponentProps } from "./withLoading";
import { IServiceApi, useService } from "../../Service/Provider";
import { App } from "antd";


import useApiCall from "./hooks/useApiCall";
import type { IServiceSendOptionConfig, RequestMode } from "./hooks/useApiCall";
import { useIntl } from "react-intl";
 
interface IWithServicEndPoint extends IServiceSendOptionConfig {
    hideMessage?: boolean;
}

interface IWithServiceOption {
    loadingOptions?: IWithLoadingOption;
    reqOnMount?: boolean;
    reqEndPoints?: IWithServicEndPoint[];
    reqMode?: RequestMode;
    reqThrowException?: boolean;
    overrideErrorNotify?: boolean;
    ErrorMessage?: React.ComponentType<any>;
}

export interface IWithServiceApi<ResponseData={}> {
    withServiceApi: IServiceApi;
    withLoadingApi: IWithLoadingApi;
    responseData: ResponseData & {
        afterApiResponse?: boolean;
    };
}

export const withService = <T={}, ResponseData={}>(option?: IWithServiceOption) => (TargetComponent: React.ComponentType<T & IWithServiceApi<ResponseData> & ITargetComponentProps<T,ResponseData>>): React.ComponentType<T>=> {
    const loadingOpt = option && option.reqEndPoints && option?.reqEndPoints?.length > 0 ? {
        defaultVisible: true,
        ...(option?.loadingOptions || {}),
    } : option?.loadingOptions;

    return withLoading({
        ...loadingOpt,
        mountWithLoading: true
    })((props) => {
        const serviceObj = useService();
        const [ ajaxLoading, setAjaxLoading ] = useState(option && option.reqEndPoints && option?.reqEndPoints?.length > 0)
        const mountChild = useMemo(() => {
            if(option?.loadingOptions?.mountWithLoading) {
                return true;
            } else {
                return !props.withLoadingApi.visible || !ajaxLoading;
            }
        }, [props.withLoadingApi, ajaxLoading]);
        const ajaxRequest = useApiCall(option?.reqEndPoints || [], option?.reqMode ?? "QueueList", option?.reqThrowException);
        const intl = useIntl();
        const app = App.useApp();
        const [ nextProps, setNextProps ] = useState({
            responseData: {
                afterApiResponse: false
            }
        });
        useEffect(() => {
            ajaxRequest()
                .then((responseData: any) => {
                    setNextProps({
                        responseData: {
                            ...responseData,
                            afterApiResponse: true
                        }
                    } as any);
                    props.withLoadingApi.hide();
                    setAjaxLoading(false);
                })
                .catch((error) => {
                    const statusCode = error?.exception?.statusCode || error.statusCode;
                    const msg = intl.formatMessage({
                        id: `error.${statusCode}`,
                        "defaultMessage": error.message || "系统内部错误，获取数据失败。"
                    });
                    !error.withoutErrorHandle && app.message.error(msg);
                    console.error(error);
                    props.withLoadingApi.hide();
                    setAjaxLoading(false);
                    setNextProps({
                        responseData: {
                            afterApiResponse: true,
                            error
                        }
                    } as any);
                });
        }, []);

        return mountChild ? <TargetComponent
            {...(props as any)}
            {...nextProps}
            withServiceApi={serviceObj}
        /> : <></>;
    });
};
